/**
 * 
 */
package x.java.tea;

import java.io.IOException;

/**
 * @author qiangli
 *
 */
public class ObjectInjector implements Injector {
	protected String id;
	
	protected Object obj;
	
	private byte[] buf;
	
	private int pos;
	
	private Injector injector;
	
	private boolean initialized;

	public ObjectInjector() {
	}
	
	public ObjectInjector(Object obj) {
		this.obj = obj;
	}
	
	public void setObject(Object obj) {
		this.obj = obj;
	}

	protected void setBuf(byte[] buf) {
		this.buf = buf;
		this.pos = 0;
	}

	protected void setBuf(Injector injector) {
		this.injector = injector;
		this.initialized = false;
	}
	
	protected void setBuf(String str) {
		setBuf(str.getBytes());
	}
	
	protected void setBuf(Object obj) {
		if (obj instanceof Injector) {
			setBuf((Injector)obj);
		} else  {
			setBuf(obj.toString());
		}
	}

	private void setInput(Object obj) {
		if (obj == null) {
			return;
		}
		if (obj instanceof byte[]) {
			setBuf((byte[]) obj);
		} else {
			setBuf(obj);
		}
	}
	
	public void init(String id) {
		doInit(id);
	}

	public int inject(byte[] b) throws IOException {
		return doInject(b);
	}
	
	protected Object getObject() {
		return obj;
	}
	
	protected final void doInit(String id) {
		this.id = id;
		this.injector = null;
		this.initialized = false; //lazy init for passed-in injector
		this.buf = null;
		this.pos = 0;
		
		Object in = getObject();
		setInput(in);
	}
	
	protected final int doInject(byte[] b) throws IOException {
		int c = -1;
		if (buf != null) {
			c = write(b);
		} else if (injector != null) {
			if (!initialized) {
				initialized = true;
				injector.init(id);
			}
			c = injector.inject(b);
		}
		return c;
	}
	
	private int write(byte[] to) {
		if (buf == null) {
			return -1;
		}
		if (pos >= buf.length) {
			pos = 0;
			buf = null;
			return -1;
		}
		int l = fill(buf,pos,to);
		pos += l;
		return l;
	}
	
	private int fill(byte[] from, int off, byte[] to) {
		int len = Math.min(from.length - off, to.length);
		for (int i=0; i<len; i++) {
			to[i] = from[i+off];
		}
		return len;
	}
}
